package com.qianxing.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.qianxing.dto.UserInfoDTO;
import com.qianxing.dto.WxUserLoginDTO;
import com.qianxing.exceptionhandler.ResponseException;
import com.qianxing.service.TbUserInfoService;
import com.qianxing.vo.UserInfoVO;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import java.util.concurrent.TimeUnit;

import static com.qianxing.utils.RedisContanct.LOGIN_TOKEN;
import static com.qianxing.utils.RedisContanct.LOGIN_USER_KEY;

/**
 * @Author:JasonLong
 * @Date:2023/5/21
 * @Time:13:51
 */
@Slf4j
@RestController
public class WxMaUserController {

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private TbUserInfoService userInfoService;

    //Redis工具类对象
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 登陆接口
     */
    @PostMapping("/login")
    public ResponseException login(@Valid @RequestBody WxUserLoginDTO userLoginDTO, BindingResult bindingResult, HttpServletRequest request) {
        boolean hasErrors = bindingResult.hasErrors();
        //表单验证
        if (hasErrors) {
            return ResponseException.error("500", "缺少参数!");
        }
        try {
            //获取用户OpenID&SessionKey
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(userLoginDTO.getCode());

            /**
             * 用户信息、用户手机号
             */
            WxMaUserInfo userInfo;
            WxMaPhoneNumberInfo phoneNoInfo;
            // TODO 判断对应的OpenId是否存在
            ResponseException userOpenId = userInfoService.getUserOpenId(session.getOpenid());
            if (BeanUtil.isEmpty(userOpenId.getData())) {
                System.out.println("用户未注册！");
                //获取用户相关
                if (!StringUtils.isBlank(session.getSessionKey())) {
                    userInfo = wxMaService.getUserService().getUserInfo(session.getSessionKey(), userLoginDTO.getEncryptedData(), userLoginDTO.getIv());
                    //解密获取用户手机号码
                    phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(session.getSessionKey(), userLoginDTO.getEncryptedData(), userLoginDTO.getIv());
                    UserInfoDTO userInfoDTO = new UserInfoDTO();
                    userInfoDTO.setUserAvatar(userInfo.getAvatarUrl());
                    userInfoDTO.setUserOpenid(session.getOpenid());
                    userInfoDTO.setUserNickname(userInfo.getNickName());
                    userInfoDTO.setUserPhone(phoneNoInfo.getPhoneNumber());
                    System.out.println(userInfoDTO);
                    Boolean isSave = userInfoService.saveUserInfo(userInfoDTO);
                    if (!isSave) {
                        return ResponseException.error("500", "存储数据失败！");
                    }
                }
            }
            //生成Token
            String token = UUID.randomUUID(true).toString();

            //将token存储到Redis并设置时效
            stringRedisTemplate.opsForValue().set(LOGIN_USER_KEY + token, session.getOpenid());
            //设置用户登录有效时间(120分钟)
            stringRedisTemplate.expire(LOGIN_USER_KEY + token, 120L, TimeUnit.MINUTES);
            //TODO 此处不应该只返回token
            //获取用户相关信息数据
            UserInfoVO userInfoVO = getUser(token);
            if (BeanUtil.isEmpty(userInfoVO)) {
                return ResponseException.error("500", "登陆失败");
            }
            request.getServletContext().setAttribute("token", token);//保存当前用户token
            userInfoVO.setToken(token);
            //返回用户信息数据
            return ResponseException.success(userInfoVO);
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return ResponseException.error("500", e.getMessage());
        } finally {
            WxMaConfigHolder.remove();//清理ThreadLocal线程变量
        }
    }

    /**
     * 获取用户信息
     *
     * @param token
     * @return
     */
    @GetMapping("/getUser")
    public UserInfoVO getUser(String token) {
        return userInfoService.getUser(token);
    }

    /**
     * 清除用户登陆数据
     *
     * @param token
     */
    @GetMapping("/clear")
    public void clearToken(String token) {
        //清除缓存
        stringRedisTemplate.delete(LOGIN_USER_KEY + token);
    }

    /**
     * 获取登陆有效状态，登录状态无效返回true
     *
     * @param token
     * @return
     */
    @GetMapping("/getExpireTime")
    public boolean getRedisTokenTime(String token) {
        Long expire = stringRedisTemplate.opsForValue().getOperations().getExpire(LOGIN_USER_KEY + token);
        if (expire < 0) {
            //键已过期
            return true;
        }
        //键未过期
        return false;
    }
}
